
`include "common_header.verilog"

//  *************************************************************************
//   File : xgxs_tx_cntl.v
//  *************************************************************************
//   This program is controlled by a written license agreement.
//   Unauthorized Reproduction or Use is Expressly Prohibited. 
// 
//  Copyright (c) 2005 Morethanip GmbH
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: xgxs_tx_cntl.v,v 1.3 2011/08/31 13:10:45 dk Exp $ 
//  Author : Muhammad Anisur Rahman
//  *************************************************************************
//  Description:
// 
//  PCS Transmit control
// 
//  *************************************************************************

module xgxs_tx_cntl (
   
   reset,
   clk,
`ifdef USE_CLK_ENA
   clk_ena,
`endif
   txd,
   txc,
   din0,
   kin0,
   din1,
   kin1,
   din2,
   kin2,
   din3,
   kin3
`ifdef MTIPXGXS_EEE_ENA
   ,
   sw_reset,
   lpi_tick,
   tx_mode_quiet,
   tx_lpi_active
`endif   
   );

input   reset;          //  Active High Reset
input   clk;            //  156.25MHz Transmit Clock
`ifdef USE_CLK_ENA
input   clk_ena;        //  Enable clk
`endif
input   [63:0] txd;     //  Transmit Data
input   [7:0] txc;      //  Transmit Control 
output  [15:0] din0;    //  Parallel byte of incoming data - Lane 0
output  [1:0] kin0;     //  Special caracter request - Lane 0
output  [15:0] din1;    //  Parallel byte of incoming data - Lane 1
output  [1:0] kin1;     //  Special caracter request - Lane 1
output  [15:0] din2;    //  Parallel byte of incoming data - Lane 2
output  [1:0] kin2;     //  Special caracter request - Lane 2
output  [15:0] din3;    //  Parallel byte of incoming data - Lane 3
output  [1:0] kin3;     //  Special caracter request - Lane 3    
`ifdef MTIPXGXS_EEE_ENA
input   sw_reset;       //  software driven sync reset
input   lpi_tick;       //  Timer Tick for all LPI timers
output  tx_mode_quiet;  //  tx_mode (0 - DATA, 1 - QUIET)
output  tx_lpi_active;  //  1 - the TX is in the Low Power State, 0 - in the Normal State

wire    tx_mode_quiet; 
wire    tx_lpi_active; 
`endif

wire    [15:0] din0; 
wire    [1:0] kin0; 
wire    [15:0] din1; 
wire    [1:0] kin1; 
wire    [15:0] din2; 
wire    [1:0] kin2; 
wire    [15:0] din3; 
wire    [1:0] kin3; 
wire    [63:0] encode_txd; 
wire    [7:0] encode_txc; 
wire    [63:0] xgmii_txd_d; 
wire    [7:0] xgmii_txc_d; 
wire    [2:0] encode_col1; 
wire    [2:0] encode_col2; 

`ifdef MTIPXGXS_EEE_ENA
wire    [1:0] encode_lpi;       // indicate LPI aligned with xgmii_txd/c_d
wire    [3:0] lpi_rnd;          // random value for LPI character insertion
wire    tx_oset_li;             // lpi indication to STM
`endif


pcs_tx_state_mc U_TX_STATE (

          .reset(reset),
          .clk(clk),
        `ifdef USE_CLK_ENA
           .clk_ena(clk_ena),
        `endif          
          .xgmii_txd(txd),
          .xgmii_txc(txc),
          .xgmii_txd_d(xgmii_txd_d),
          .xgmii_txc_d(xgmii_txc_d),
          .encode_col1(encode_col1),
          .encode_col2(encode_col2)
        `ifdef MTIPXGXS_EEE_ENA
          ,
          .encode_lpi(encode_lpi)
        `endif
          );

pcs_tx_encoder U_TX_ENCOD1 (

          .reset(reset),
          .clk(clk),
        `ifdef USE_CLK_ENA
           .clk_ena(clk_ena),
        `endif
          .xgmii_txd_d(xgmii_txd_d[31:0]),
          .xgmii_txc_d(xgmii_txc_d[3:0]),
          .encode_col(encode_col1),
        `ifdef MTIPXGXS_EEE_ENA
          .encode_lpi(encode_lpi[0]),
          .encode_lpi_rnd(lpi_rnd[1:0]),
        `endif
          .encode_txd(encode_txd[31:0]),
          .encode_txc(encode_txc[3:0]));

pcs_tx_encoder U_TX_ENCOD2 (

          .reset(reset),
          .clk(clk),
        `ifdef USE_CLK_ENA
           .clk_ena(clk_ena),
        `endif
          .xgmii_txd_d(xgmii_txd_d[63:32]),
          .xgmii_txc_d(xgmii_txc_d[7:4]),
          .encode_col(encode_col2),
        `ifdef MTIPXGXS_EEE_ENA
          .encode_lpi(encode_lpi[1]),
          .encode_lpi_rnd(lpi_rnd[3:2]),
        `endif
          .encode_txd(encode_txd[63:32]),
          .encode_txc(encode_txc[7:4]));
          
//  --------------------------------------------- //
//  Mapping the decoded signal to the output port //
//  --------------------------------------------- //

//  Lane 0
//  ------

assign din0[7:0]  = encode_txd[7:0]; 
assign kin0[0]    = encode_txc[0]; 
assign din0[15:8] = encode_txd[39:32]; 
assign kin0[1]    = encode_txc[4]; 

//  Lane 1
//  ------

assign din1[7:0]  = encode_txd[15:8]; 
assign kin1[0]    = encode_txc[1]; 
assign din1[15:8] = encode_txd[47:40]; 
assign kin1[1]    = encode_txc[5]; 

//  Lane 2
//  ------

assign din2[7:0]  = encode_txd[23:16]; 
assign kin2[0]    = encode_txc[2]; 
assign din2[15:8] = encode_txd[55:48]; 
assign kin2[1]    = encode_txc[6]; 

//  Lane 3
//  ------

assign din3[7:0]  = encode_txd[31:24]; 
assign kin3[0]    = encode_txc[3]; 
assign din3[15:8] = encode_txd[63:56]; 
assign kin3[1]    = encode_txc[7]; 

// ---------------------------------------------
// EEE support
// ---------------------------------------------

`ifdef MTIPXGXS_EEE_ENA

        // reusing the //A// randomizer for the lanes
        
        lfsr2step U_LPIRND (

                .reset(reset),
                .clk(clk),
              `ifdef USE_CLK_ENA
                .clk_ena(tx_oset_li),   // run permanently when LPI is active
              `endif    
                .lsb(),
                .x_lsb(lpi_rnd));

        // LPI handshaking statemachine
                
        assign tx_oset_li = encode_lpi[0] | encode_lpi[1];      // note: signals are stable while clk_ena=0.

        xgxs_tx_stm48_9a U_TXSTM489A (
   
                .reset(reset),
                .sw_reset(sw_reset),
                .clk(clk),
                .tx_oset_li(tx_oset_li),
                .lpi_tick(lpi_tick),
                .tx_mode_quiet(tx_mode_quiet),
                .tx_lpi_active(tx_lpi_active));
        
        
`endif

endmodule // module xgxs_tx_cntl